package com.qipay.admin.order.service;

import com.qipay.admin.order.vo.OrderVo;
import com.qipay.admin.utils.SiteHelper;
import com.qipay.baas.model.Order;
import com.qipay.baas.model.Sp;
import com.qipay.cpaccount.CpAccountService;
import com.qipay.excel.service.ExcelService;
import com.qipay.excel.vo.Cell;
import com.qipay.order.config.OrderChannelEnum;
import com.qipay.order.config.OrderStateEnum;
import com.qipay.order.service.OrderService;
import com.qipay.order.vo.OrderListItem;
import com.qipay.order.vo.OrderSumVo;
import com.qipay.security.UserDetailsServiceImpl;
import com.qipay.sp.SpService;
import com.qipay.user.entity.UserLevel;
import io.jsonwebtoken.lang.Assert;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

/**
 * Creator: Yao
 * Date:    2017/9/21
 * For:
 * Other:
 */
@Service
public class OrderLogicService {

    private static Logger logger = LoggerFactory.getLogger(OrderLogicService.class);


    @Autowired
    OrderService orderService;
    @Autowired
    CpAccountService accountService;
    @Autowired
    ExcelService excelService;

    @Autowired
    SpService spService;

    public OrderSumVo sumBy(String querysql) {
        // check
        Assert.isTrue(StringUtils.isNotBlank(querysql));
        // init
        OrderSumVo orderSumVo = orderService.sumOrder(querysql);

        return orderSumVo;
    }

    public long countBy(String querysql) {
        // check
        Assert.isTrue(StringUtils.isNotBlank(querysql));
        // init
        long total = orderService.countBy(querysql);

        return total;
    }

    public long amountCount(String querysql) {
        // check
        Assert.isTrue(StringUtils.isNotBlank(querysql));

        // init
        long amountCount = orderService.amountCount(querysql);

        return amountCount;
    }

    public long feeCount(String querysql) {

        // check
        Assert.isTrue(StringUtils.isNotBlank(querysql));

        // init
        long feeCount = orderService.feeCount(querysql);

        return feeCount;
    }

    public List<List<String>> listBy(String querysql,Object offset,Object rows) {

        return list(querysql,offset,rows);
    }

    public OrderVo get(Long orderId) {

        // check
        Assert.notNull(orderId);

        // query
        OrderVo q = new OrderVo();
        Order p = orderService.get(orderId);
        if (null != p) {
            BeanUtils.copyProperties(p, q);
            q.setAmount(Double.valueOf(p.getAmount()));
            q.setActualAmount(Double.valueOf(p.getActualAmount()));
            q.setAdvanceAmount(Double.valueOf(p.getAdvanceAmount()));
            q.setDisableAmount(Double.valueOf(p.getDisableAmount()));
            q.setFee(Double.valueOf(p.getFee()));
            q.setAgentFee(null == p.getAgentFee() ? 0 : Double.valueOf(p.getAgentFee()));
            q.setSpFee(Double.valueOf(p.getSpFee()));
            fill(q);
        }

        return q;
    }

    /***
     * 金额转换 & 状态、频道等状态名称转换
     * @param order
     */
    private void fill(OrderVo order) {

        if (null == order)
            return;

        order.setAmount(order.getAmount() / 100.0);
        order.setActualAmount(order.getActualAmount() / 100.0);
        order.setAdvanceAmount(order.getAdvanceAmount() / 100.0);
        order.setDisableAmount(order.getDisableAmount() / 100.0);
        order.setFee(order.getFee() / 100.0);
        order.setAgentFee(order.getAgentFee() / 100.0);
        order.setAgentFee(order.getAgentFee() / 100.0);

        order.setStateName(OrderStateEnum.getInfo(order.getState()));
        order.setChannelName(OrderChannelEnum.getInfo(order.getChannelType()));
    }

    @Transactional
    public void freeze(UserDetailsServiceImpl.LoginUserDetails loginUser, Long orderId) {
        // check
        Assert.notNull(loginUser, "未提供操作人员");
        Assert.isTrue(loginUser.getLevel() == UserLevel.ADMIN, "无该操作权限");
        Assert.notNull(orderId, "未提供订单ID");
        Order order = orderService.get(orderId);
        Assert.notNull(order, "未找到指定订单");
        Assert.isTrue(order.getState().equals(OrderStateEnum.SUCCESS.getType()), "该订单尚未支付");
        Long cpId = order.getCpId();
        Assert.notNull(cpId, "订单未指定 CP");
        // update
        order.setState(OrderStateEnum.FREEZED.getType());
        orderService.update(order);
    }

    @Transactional
    public void unfreeze(UserDetailsServiceImpl.LoginUserDetails loginUser, Long orderId) {
        // check
        Assert.notNull(loginUser, "未提供操作人员");
        Assert.isTrue(loginUser.getLevel() == UserLevel.ADMIN, "无该操作权限");
        Assert.notNull(orderId, "未提供订单ID");
        Order order = orderService.get(orderId);
        Assert.notNull(order, "未找到指定订单");
        Assert.isTrue(order.getState().equals(OrderStateEnum.FREEZED.getType()), "该订单非冻结状态");
        // update
        order.setState(OrderStateEnum.SUCCESS.getType());
        orderService.update(order);

    }


    // Common
    public List<List<String>> list(String querysql,Object offset,Object rowss) {
        // check
        Assert.isTrue(StringUtils.isNotBlank(querysql));
        // init
        List<List<String>> datas = new ArrayList<>();
        List<OrderVo> voList = new ArrayList<>();
        List<OrderListItem> list = orderService.listBy(querysql,offset,rowss);

        // fill
        if (CollectionUtils.isNotEmpty(list)) {
            for (Order p : list) {
                OrderVo q = new OrderVo();
                BeanUtils.copyProperties(p, q);
                q.setAmount(Double.valueOf(p.getAmount()));
                q.setActualAmount(Double.valueOf(p.getActualAmount()));
                q.setAdvanceAmount(Double.valueOf(p.getAdvanceAmount()));
                q.setDisableAmount(Double.valueOf(p.getDisableAmount()));
                q.setFee(Double.valueOf(p.getFee()));
                q.setAgentFee(null == p.getAgentFee() ? 0 : Double.valueOf(p.getAgentFee()));
                q.setSpFee(Double.valueOf(p.getSpFee()));
                fill(q);
                voList.add(q);
            }
        }

        // convert
        if (CollectionUtils.isNotEmpty(voList)) {
            for (OrderVo p : voList) {
                // init
                List<String> data = new ArrayList<>();

                // fill
                data.add(p.getId().toString());
                data.add(p.getCpName());
                data.add(p.getCpId().toString());
                data.add(p.getSpId().toString());
                data.add(p.getBody());
                data.add(StringUtils.isNotBlank(p.getTradeNo()) ? p.getTradeNo() : "");
                data.add(StringUtils.isNotBlank(p.getOutTradeNo()) ? p.getOutTradeNo() : "");
                data.add(StringUtils.isNotBlank(p.getSpTradeNo()) ? p.getSpTradeNo() : "");
                data.add(SiteHelper.getDefaultTimeFormat(p.getCreateTime()));
                data.add(SiteHelper.getDefaultTimeFormat(p.getFinishTime()));
                data.add(SiteHelper.getMoneyFormatAll(Double.valueOf(p.getAmount())));
                data.add(SiteHelper.getMoneyFormatAll(Double.valueOf(p.getFee())));
                data.add(p.getChannelName());      //支付方式   支付宝扫码之类的
                data.add(p.getStateName());        //状态       未支付,订单取消,已支付,已冻结,支付失败
                data.add(p.getState().toString());
                Sp sp = spService.get(p.getSpId().intValue());
                data.add(sp==null?"":sp.getBank());

                // add
                datas.add(data);
            }
        }

        return datas;
    }

    // Export

    public HSSFWorkbook exportBy(String querysql,Object offset,Object rowss) throws ParseException, IOException {

        // init.excel
        List<Cell> list = new ArrayList<>();
        int rowIdx = 0;
        int cellIdx = 0;
        List<List<String>> detailList = list(querysql,offset,rowss);
        List<List<String>> exportList = new ArrayList<>();

        // init.title
        list.add(new Cell(rowIdx, cellIdx++, "ID"));
        list.add(new Cell(rowIdx, cellIdx++, "商户"));
        list.add(new Cell(rowIdx, cellIdx++, "商户 ID"));
        list.add(new Cell(rowIdx, cellIdx++, "sp ID"));
        list.add(new Cell(rowIdx, cellIdx++, "商品描述"));
        list.add(new Cell(rowIdx, cellIdx++, "系统订单"));
        list.add(new Cell(rowIdx, cellIdx++, "商户订单"));
        list.add(new Cell(rowIdx, cellIdx++, "订单"));
        list.add(new Cell(rowIdx, cellIdx++, "创建时间"));
        list.add(new Cell(rowIdx, cellIdx++, "完成时间"));
        list.add(new Cell(rowIdx, cellIdx++, "金额"));
        list.add(new Cell(rowIdx, cellIdx++, "手续费"));
        list.add(new Cell(rowIdx, cellIdx++, "计费渠道"));
        list.add(new Cell(rowIdx, cellIdx++, "状态"));
        list.add(new Cell(rowIdx, cellIdx++, "操作"));
        list.add(new Cell(rowIdx, cellIdx++, "sp渠道"));

        // init.text
        if (CollectionUtils.isNotEmpty(detailList)) {
            for (List<String> p : detailList) {

                List<String> q = new ArrayList<>();

               q.add(p.get(0));
               q.add(p.get(1));
               q.add(p.get(2));
               q.add(p.get(3));
               q.add(p.get(4));
               q.add(p.get(5));
               q.add(p.get(6));
                q.add(p.get(7));
                q.add(p.get(8));
                q.add(p.get(9));
                q.add(p.get(10));
                q.add(p.get(11));
                q.add(p.get(12));
                q.add(p.get(13));
                q.add(p.get(14));
                q.add(p.get(15));
                exportList.add(q);
            }
        }

        // init.content
        excelService.fill(list, exportList, rowIdx);

        return excelService.fill("", list);
    }

    /**
     * 订单查询，条件转换成sql
     * @param params
     * @return
     */
    public String general(Object... params) {

        UserLevel level = (UserLevel) params[0];
        String username = (String) params[1];
        String cpId = (String) params[2];
        Integer channel = (Integer) params[3];
        Byte state = (Byte) params[4];
        String tradeNo = (String) params[5];
        String outTradeNo = (String) params[6];
        String spTradeNo = (String) params[7];
        String from = (String) params[8];
        String to = (String) params[9];
        Long spId = null;
        if (params.length>10){
            spId = (Long) params[10];
        }
        String agentId = null;
        if (level == UserLevel.AGENT) {
            agentId = username;
        } else if (level == UserLevel.CP) {
            cpId = username;
        }

        String sql = "select o.*, ci.name as cpName "
                + "from `order` o "
                + "inner join cp c on o.cp_id= c.id and c.account_state= 2 "
                + "left join cp_info ci on o.cp_id= ci.cp_id "
                + "where 1= 1 ";
        String param = "";

        if (StringUtils.isNotBlank(cpId))
            param += String.format(" and o.cp_id= %s", cpId);
        if (null != spId &&  spId!=0)
            param += String.format(" and o.sp_id= %s", spId);

        if (StringUtils.isNotBlank(agentId)) {
            param += String.format(" and c.agent_id = %s", agentId);
        }
        if (null != channel && channel != 0) {
            param += String.format(" and o.channel_type= %s", channel);
        }
        if (null != state && state != 0) {
            param += String.format(" and o.`state`= %s", state);
        }
        if (StringUtils.isNotBlank(tradeNo)) {
            param += String.format(" and o.trade_no like '%%%s%%'", tradeNo);
        }
        if (StringUtils.isNotBlank(spTradeNo)) {
            param += String.format(" and o.sp_trade_no like '%%%s%%'", spTradeNo);
        }
        if (StringUtils.isNotBlank(outTradeNo)) {
            param += String.format(" and o.out_trade_no like '%%%s%%'", outTradeNo);
        }
        if (StringUtils.isNotBlank(from)) {
            param += String.format(" and o.create_time>= '%s'", from);
        }
        if (StringUtils.isNotBlank(to)) {
            param += String.format(" and o.create_time<= '%s'", to);
        }

        return sql += param;
    }

}
